package com.mf.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mf.entity.bo.DeptBo;
import com.mf.entity.dto.dept.DeptDto;
import com.mf.entity.request.dept.DeptRequest;
import com.mf.entity.vo.RosterVo;
import com.mf.entity.vo.dept.DeptAndPositionVo;
import com.mf.entity.vo.dept.DeptVo;
import com.mf.entity.vo.dept.PositionVo;
import com.mf.mapper.DeptMapper;

import com.mf.service.IDeptService;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mf.service.IPositionService;
import io.github.heollhai.common.config.exceptions.GraceException;
import io.github.heollhai.common.entity.request.publicRequest.UpdateStatusRequest;
import io.github.heollhai.common.enums.EnableOrDisableEnum;
import io.github.heollhai.common.utils.MybatisPlusUtils;
import io.github.heollhai.common.utils.VerifyUtils;
import io.github.heollhai.common.utils.enums.EnumUtils;
import io.github.heollhai.common.utils.tree.TreeUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 部门表 服务实现类
 *
 * @author mf
 * @since 2024-09-20
 */
@Service
@Slf4j
public class DeptServiceImpl extends ServiceImpl<DeptMapper, DeptBo> implements IDeptService {
    @Resource
    private DeptMapper deptMapper;

    @Resource
    private IPositionService positionService;


    /**
     * 删除
     */
    @Override
    public Integer deleteById(Integer id) {
        if (positionService.isJobIdByDeptId(id)) {
            GraceException.display("该部门下有岗位，无法删除");
        }
        return deptMapper.deleteById(id);
    }

    @Override
    public Integer changeStatus(UpdateStatusRequest<Integer> updateStatusRequest) {
        if(EnumUtils.existsInEnum(EnableOrDisableEnum.class,updateStatusRequest.getStatus())){
            GraceException.display("状态不合法");
        }
        DeptBo deptBo = new DeptBo();
        deptBo.setId(updateStatusRequest.getId());
        deptBo.setStatus(updateStatusRequest.getStatus());

        return deptMapper.updateById(deptBo);
    }

    /**
     * 修改状态
     */
    @Override
    public List<DeptAndPositionVo> listFindByDeptAndPosition() {

        List<DeptBo> deptBos = deptMapper.selectList(null);
        List<DeptAndPositionVo> deptAndPositionVos = MybatisPlusUtils.changeDataClass(deptBos, DeptAndPositionVo.class);
        deptAndPositionVos = TreeUtils.getRoot(deptAndPositionVos);
        setPosition(deptAndPositionVos, positionService.listFindTreeByDeptIdGroup());
        return deptAndPositionVos;
    }

    /**
     * 递归设置岗位
     */
    private void setPosition(List<DeptAndPositionVo> deptAndPositionVos, Map<Integer, List<PositionVo>> listMap) {
        for (DeptAndPositionVo deptAndPositionVo : deptAndPositionVos) {
            // 获取岗位 按照部门id分组
            List<PositionVo> positionList = listMap.get(deptAndPositionVo.getId());

            // 为部门下面设置岗位
            if (deptAndPositionVo.getType() == 1) {
                deptAndPositionVo.setPositionList(positionList);
            }
            // 对部门进行递归
            if (VerifyUtils.isNotEmpty(deptAndPositionVo.getChildren())) {
                setPosition(deptAndPositionVo.getChildren(), listMap);
            }
        }
    }

    /**
     * 查询
     */
    @Override
    public List<DeptVo> findByList(DeptRequest deptRequest) {
        LambdaQueryWrapper<DeptBo> wrapper = new LambdaQueryWrapper<>();
        if (VerifyUtils.isNotEmpty(deptRequest.getStatus())) {
            wrapper.eq(DeptBo::getStatus, deptRequest.getStatus());
        }
        if (VerifyUtils.isNotEmpty(deptRequest.getRemark())) {
            wrapper.like(DeptBo::getRemark, deptRequest.getRemark());
        }

        if (VerifyUtils.isNotEmpty(deptRequest.getName())) {
            wrapper.like(DeptBo::getName, deptRequest.getName());
        }
        return MybatisPlusUtils.changeDataClass(deptMapper.selectList(wrapper), DeptVo.class);
    }

    /**
     * 获取所有启用部门
     */
    @Override
    public List<DeptVo> listFindByEnable() {
        LambdaQueryWrapper<DeptBo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DeptBo::getStatus, EnableOrDisableEnum.ENABLE.value);
        return MybatisPlusUtils.changeDataClass(deptMapper.selectList(wrapper), DeptVo.class);
    }

    /**
     * 对查询的部门按照id进行分组
     */
    @Override
    public Map<Integer, List<DeptVo>> listFindTreeByDeptIdGroup() {
        List<DeptVo> deptVos = listFindByEnable();
        return deptVos.stream().collect(Collectors.groupingBy(DeptVo::getId));
    }

    /**
     * 新增
     */
    @Override
    public Integer insert(DeptDto dept) {
        DeptBo deptBo = new DeptBo();
        BeanUtils.copyProperties(dept, deptBo);
        if (VerifyUtils.isNotEmpty(dept.getId())) {
            if(dept.getId().equals(dept.getPid())){
                GraceException.display("上级部门不能为自身");
            }

            return deptMapper.updateById(deptBo);
        }
        return deptMapper.insert(deptBo);
    }

    /**
     * 对查询数据写入部门和岗位信息
     */
    @Override
    public Page<RosterVo> setDeptAndJob(Page<RosterVo> rosterVoPage) {
        Map<Integer, List<PositionVo>> positionById = positionService.listFindAllByIdGroup();
        Map<Integer, List<DeptVo>> deptById = listFindTreeByDeptIdGroup();

        for (RosterVo record : rosterVoPage.getRecords()) {
            if(VerifyUtils.isEmpty(record.getEntryDeptId())){
                continue;
            }

            deptById.get(record.getEntryDeptId())
                    .stream()
                    .findFirst()
                    .ifPresent(deptVo -> record.setEntryDept(deptVo.getName()));


            if(VerifyUtils.isEmpty(record.getEntryJobId())){
                continue;
            }
            positionById.get(record.getEntryJobId())
                    .stream()
                    .findFirst()
                    .ifPresent(positionVo -> record.setEntryJob(positionVo.getName()));
        }
        return rosterVoPage;
    }
}
